package peerToPeerFacebook.proj;

import java.io.IOException;
import java.io.Serializable;

/** Proxy class that is attached to RPC server and distributes calls to various part of the framework */
public class PaxosProxy
{
    /** Paxos state machine binding */
    protected PaxosStateMachine paxos = null;
    
    /** FBNode to use when accessing disk */
    protected FBNode node = null;
    
    /** Initializes paxos proxy class, starts all required permanent paxos instances 
     */
    public PaxosProxy(FBNode node) throws IOException
    {
        // TODO: Initialize paxos acceptor
        paxos = new PaxosStateMachine(node);
        this.node = node;
    }
    
    /* Proxy methods */
    /* Paxos State Machine */
    
    /** Method that is called by paxos proposer to supply new value that has been accepted by paxos group.
     * 
     * @param clientID Client ID set by RPC layer. Ignored
     * @param commandID ID of the command that is being learned.
     * @param value Value that is being learned.
     * @param ourProposal Is this command is the same one that node made proposal a little bit earlier.
     */
    public void learn(int clientID, int commandID, Serializable value, boolean ourProposal)
    {
        paxos.learn(commandID, value, ourProposal);
    }
    
    /* Paxos acceptor methods */
    public PrepareResponse prepare(int clientID, int newInstanceNo, String newProposalNo)
    {
        PaxosAcceptor pa = new PaxosAcceptor(node);
        return pa.prepare(newInstanceNo, newProposalNo);
    }

    public boolean accept(int clientID, int paxosInstance, String proposalNo, PaxosCommand newCommand)
    {
        PaxosAcceptor pa = new PaxosAcceptor(node);
        return pa.accept(paxosInstance, proposalNo, newCommand);        
    }
    
    /* FileIO commands. As these commands requires consensus on the PSM, they will always return CallPending object.
     * Furthermore we do not really care about ClientID, thus it is always ignored as well. */
    public CallPending createFile(int clientID, int sequenceID, String filename) throws IOException
    {
        return paxos.execute(new PaxosCommand(clientID, sequenceID, IServerFileIO.CreateFileMethodName,
                new Serializable [] { filename }));
    }
    
    public CallPending getFileContents(int clientID, int sequenceID, String filename) throws IOException
    {
        return paxos.execute(new PaxosCommand(clientID, sequenceID, IServerFileIO.GetFileContentsMethodName,
                new Serializable [] { filename }));        
    }

    public CallPending putContentsToFile(int clientID, int sequenceID, String filename, String contents) throws IOException
    {
        return paxos.execute(new PaxosCommand(clientID, sequenceID, IServerFileIO.PutContentsToFileMethodName,
                new Serializable [] { filename, contents }));         
    }

    public CallPending appendContentsToFile(int clientID, int sequenceID, String filename, String contents) throws IOException
    {
        return paxos.execute(new PaxosCommand(clientID, sequenceID, IServerFileIO.AppendContentsToFileMethodName,
                new Serializable [] { filename, contents }));        
    }
    
    public CallPending deleteFile(int clientID, int sequenceID, String filename) throws IOException
    {
        return paxos.execute(new PaxosCommand(clientID, sequenceID, IServerFileIO.DeleteFileMethodName,
                new Serializable [] { filename }));                
    }
}
